
/*
 * Java class "Driver.java" generated from Poseidon for UML.
 * Poseidon for UML is developed by <A HREF="http://www.gentleware.com">Gentleware</A>.
 * Generated with <A HREF="http://jakarta.apache.org/velocity/">velocity</A> template engine.
 */
package jcs;

import robocode.HitRobotEvent;
import robocode.HitWallEvent;


/**
 * <p></p>
 * 
 * @poseidon-object-id [sm$89848d:ffe131bfd5:-7f94]
 */
public class Driver {

  ///////////////////////////////////////
  // attributes


/**
 * <p>Represents ...</p>
 * @poseidon-object-id [sm$3cc05f:ffee92588c:-7e5a]
 */
    private final int TIMER_LENGTH = 12; 

/**
 * <p>Represents ...</p>
 * @poseidon-object-id [sm$3cc05f:ffee92588c:-7e5f]
 */
    private final double INNER_DODGE = 10.0; 

/**
 * <p>Represents ...</p>
 * @poseidon-object-id [sm$3cc05f:ffee92588c:-7e5e]
 */
    private final double OUTER_DODGE = 80.0; 

/**
 * <p>Represents ...</p>
 * @poseidon-object-id [sm$3cc05f:ffee92588c:-7e5d]
 */
    private int timer = 0; 

/**
 * <p>Represents ...</p>
 * @poseidon-object-id [sm$3cc05f:ffee92588c:-7e5b]
 */
    private Coord dodge; 

/**
 * <p>Represents ...</p>
 * @poseidon-object-id [sm$3cc05f:ffee92588c:-7eeb]
 */
    private boolean forward = true; 

/**
 * <p>Represents ...</p>
 * @poseidon-object-id [sm$3cc05f:ffef686712:-7fab]
 */
    private long ramTimer = 0; 

/**
 * <p>Represents ...</p>
 * @poseidon-object-id [sm$3cc05f:ffef686712:-7fa9]
 */
    private final long RAM_TIMER_LENGTH = 7; 

/**
 * <p>Represents ...</p>
 * @poseidon-object-id [sm$80d028:fff4282a7c:-7ff1]
 */
    private final double WALL_AVOID = 35.0; 

   ///////////////////////////////////////
   // associations

/**
 * 
 * @poseidon-object-id [sm$5cb0bb:ffee7186d0:-7fbe]
 */
    private AntiGrav ag; 
/**
 * <p></p>
 * @poseidon-object-id [sm$3040c5:ffee75eaf6:-7f82]
 */
    public Seth seth; 


  ///////////////////////////////////////
  // operations


/**
 * <p>Does ...</p>
 * 
 * @poseidon-object-id [sm$bb9f5b:ffea48a5fd:-7ff4]
 * @param _seth 
 */
    public  Driver(Seth _seth) {        
        seth = _seth;
        ag = new AntiGrav(_seth);
    } // end Driver        

/**
 * <p>Does ...</p>
 * 
 * @poseidon-object-id [sm$bb9f5b:ffea48a5fd:-7fef]
 */
    public void doMove() {        
        Coord destination = ag.calcCoord(seth.getCurrentPos());
        // destination = wallAvoid( destination );
        destination = dodge( destination );
        //seth.setMaxVelocity( 6.0 );
        gotoCoord( destination );
    } // end doMove        

/**
 * <p>Does ...</p>
 * 
 * @poseidon-object-id [sm$3cc05f:ffee92588c:-7ff6]
 * @param _coord 
 */
    public void gotoCoord(Coord _coord) {        
        double distance = seth.getCurrentPos().calcDist( _coord );
        double resultantHeading = seth.getCurrentPos().calcHeading( _coord ) - seth.getHeadingRadians();
        
        // Calculate turn speed
        if(distance > 0.0)
        {
            double calcSpeed = 10.0 / ((Math.abs(resultantHeading) / distance)  + 0.75);
            if(calcSpeed > 8.0)
            {
                calcSpeed = 8.0;
            }
            seth.setMaxVelocity(calcSpeed);
        }
        
        if((resultantHeading > 0) && (resultantHeading < Math.PI))
        {
            if( resultantHeading < (Math.PI / 2.0) )
            {
                forward = true;
                seth.setTurnRightRadians(Math.abs(resultantHeading));  
            }
            else
            {
                forward = false;
                seth.setTurnLeftRadians(Math.PI - Math.abs(resultantHeading));
            }
        }
        else if(resultantHeading >= Math.PI)
        {
            if( resultantHeading < (3.0 * Math.PI / 2.0) )
            {
                forward = false;
                seth.setTurnRightRadians(Math.abs(resultantHeading) - Math.PI);
            }
            else
            {
                forward = true;
                seth.setTurnLeftRadians(2.0 * Math.PI - Math.abs(resultantHeading));
            }
        }
        else if((resultantHeading <= 0) && (resultantHeading >= -Math.PI))
        {
            if( resultantHeading < (Math.PI / 2.0) )
            {
                forward = true;
                seth.setTurnLeftRadians(Math.abs(resultantHeading));                
            }            
            else
            {
                forward = false;
                seth.setTurnRightRadians(Math.PI - Math.abs(resultantHeading));
            } 
        }
        else
        {
            if( resultantHeading < (3.0 * Math.PI / 2.0) )
            {
                forward = false;
                seth.setTurnLeftRadians(Math.abs(resultantHeading) - Math.PI);                
            }            
            else
            {
                forward = true;
                seth.setTurnRightRadians(2.0 * Math.PI - Math.abs(resultantHeading));
            }
        }
        
        if(forward)
        {
            seth.setAhead(distance);
        }
        else
        {
            seth.setBack(distance);
        }
    } // end gotoCoord        

/**
 * <p>Represents ...</p>
 * 
 * @poseidon-object-id [sm$3cc05f:ffee92588c:-7eec]
 * @return 
 */
    public boolean isForward() {        
        return forward;
    } // end isForward        

/**
 * <p>Represents ...</p>
 * 
 * @poseidon-object-id [sm$3cc05f:ffee92588c:-7ee9]
 * @param _forward 
 */
    public void setForward(boolean _forward) {        
        forward = _forward;
    } // end setForward        

/**
 * <p>Does ...</p>
 * 
 * @poseidon-object-id [sm$3cc05f:ffee92588c:-7e60]
 * @return 
 * @param _coord 
 */
    public Coord dodge(Coord _coord) {        
        if(timer == 0)
        {
            double bearing = Math.random() * 2.0 * Math.PI;
            double distance = INNER_DODGE + Math.random() * (OUTER_DODGE - INNER_DODGE);
            dodge = _coord.minus(_coord.getCoordFromScan( bearing, distance ));
            _coord = _coord.plus(dodge);
            timer = TIMER_LENGTH;
            //System.out.println("Dodge this! "+dodge.toString()+" at ticks "+seth.getTicks());
        }
        else
        {
             _coord = _coord.plus(dodge);
             timer--;
             if(ramTimer > 0)
            {
                 ramTimer--;
            }
        }
        return _coord;
    } // end dodge        

/**
 * <p>Does ...</p>
 * 
 * @poseidon-object-id [sm$d73256:ffef5f041e:-7ff6]
 * @param e 
 */
    public void hitRobotEvent(HitRobotEvent e) {        
        if(ramTimer == 0)
        {
            dodge.setX(-dodge.getX());
            dodge.setY(-dodge.getY());
            ramTimer = RAM_TIMER_LENGTH;
        }
    } // end hitRobotEvent        

/**
 * <p>Does ...</p>
 * 
 * @poseidon-object-id [sm$80d028:fff4282a7c:-7ff6]
 * @return 
 * @param _coord 
 */
    public Coord wallAvoid(Coord _coord) {        
        if(_coord.getX() < (OUTER_DODGE + WALL_AVOID))
        {
            _coord.setX(OUTER_DODGE + WALL_AVOID);
        }
        if(_coord.getY() < (OUTER_DODGE + WALL_AVOID))
        {
            _coord.setY(OUTER_DODGE + WALL_AVOID);
        }
        if((seth.getBattleFieldWidth() - _coord.getX()) < (OUTER_DODGE + WALL_AVOID))
        {
            _coord.setX(seth.getBattleFieldWidth() - (OUTER_DODGE + WALL_AVOID));
        }
        if((seth.getBattleFieldHeight() - _coord.getY()) < (OUTER_DODGE + WALL_AVOID))
        {
            _coord.setY(seth.getBattleFieldHeight() - (OUTER_DODGE + WALL_AVOID));
        }        
        return _coord;
    } // end wallAvoid        

/**
 * <p>Does ...</p>
 * 
 * @poseidon-object-id [sm$5292e6:100050d2167:-7fd5]
 * @param e 
 */
    public void hitWallEvent(HitWallEvent e) {        
        if(ramTimer == 0)
        {
            dodge.setX(-dodge.getX());
            dodge.setY(-dodge.getY());
            ramTimer = RAM_TIMER_LENGTH;
        }
    } // end hitWallEvent        

 } // end Driver


